import mongoose from 'mongoose';
import { System, ISystemDocument, SystemStatus, SystemType } from '../models/system';
import { IUser } from '../models/user';
import { BaseDAO } from './BaseDAO';

/**
 * 系统数据访问对象
 * 提供系统相关的数据库操作方法
 */
export class SystemDAO extends BaseDAO<ISystemDocument> {
  constructor() {
    super(System);
  }

  /**
   * 创建新系统
   * @param systemData 系统数据
   * @returns 创建的系统文档
   */
  async create(systemData: {
    systemName: string;
    systemCode: string;
    description?: string;
    systemType: SystemType;
    version?: string;
    createdBy?: mongoose.Types.ObjectId;
    callbackUrl?: string;
    allowedOrigins?: string[];
    metadata?: Record<string, any>;
    status?: SystemStatus;
  }): Promise<ISystemDocument> {
    // 验证系统代码唯一性
    const existingSystem = await this.model.findOne({ systemCode: systemData.systemCode });
    if (existingSystem) {
      throw new Error(`系统代码 ${systemData.systemCode} 已存在`);
    }

    // 验证创建者ID
    if (systemData.createdBy && !mongoose.Types.ObjectId.isValid(systemData.createdBy)) {
      throw new Error('无效的创建者ID');
    }

    const system = new this.model({
      ...systemData,
      createdBy: systemData.createdBy || null
    });
    return await system.save();
  }

  /**
   * 根据系统代码查找系统
   * @param systemCode 系统代码
   * @returns 系统文档或null
   */
  async findByCode(systemCode: string): Promise<ISystemDocument | null> {
    if (!systemCode || typeof systemCode !== 'string' || systemCode.trim() === '') {
      throw new Error('系统代码不能为空');
    }
    return await this.model.findOne({ systemCode }).exec();
  }

  /**
   * 更新系统信息
   * @param id 系统ID
   * @param updateData 更新数据
   * @returns 更新后的系统文档
   */
  async update(id: mongoose.Types.ObjectId | string, updateData: {
    name?: string;
    description?: string;
    version?: string;
    maintainer?: mongoose.Types.ObjectId;
    apiEndpoint?: string;
    status?: SystemStatus;
    settings?: Record<string, any>;
  }, updatedBy?: mongoose.Types.ObjectId): Promise<ISystemDocument | null> {
    if (!mongoose.Types.ObjectId.isValid(id)) {
      throw new Error('无效的系统ID');
    }

    // 验证更新者ID
    if (!updatedBy || !mongoose.Types.ObjectId.isValid(updatedBy)) {
      throw new Error('无效的更新者ID');
    }

    // 验证维护者ID
    if (updateData.maintainer && !mongoose.Types.ObjectId.isValid(updateData.maintainer)) {
      throw new Error('无效的维护者ID');
    }

    // 映射字段名
    const mappedData: any = {};
    if (updateData.name) mappedData.systemName = updateData.name;
    if (updateData.description) mappedData.description = updateData.description;
    if (updateData.version) mappedData.version = updateData.version;
    if (updateData.maintainer) mappedData.maintainer = updateData.maintainer;
    if (updateData.apiEndpoint) mappedData.callbackUrl = updateData.apiEndpoint;
    if (updateData.status) mappedData.status = updateData.status;
    if (updateData.settings) mappedData.metadata = updateData.settings;

    const system = await this.model.findByIdAndUpdate(
      id,
      { ...mappedData, updatedBy, updatedAt: new Date() },
      { new: true, runValidators: true }
    );

    return system;
  }

  /**
   * 更新系统状态
   * @param id 系统ID
   * @param status 新状态
   * @returns 更新后的系统文档
   */
  async updateStatus(id: mongoose.Types.ObjectId | string, status: SystemStatus, updatedBy?: mongoose.Types.ObjectId): Promise<ISystemDocument> {
    if (!mongoose.Types.ObjectId.isValid(id)) {
      throw new Error('无效的系统ID');
    }

    if (!Object.values(SystemStatus).includes(status)) {
      throw new Error('无效的系统状态');
    }

    const updateData: any = { status, updatedAt: new Date() };
    if (updatedBy) {
      updateData.updatedBy = updatedBy;
    }

    const system = await this.model.findByIdAndUpdate(
      id,
      updateData,
      { new: true }
    ).exec();
    if (!system) {
      throw new Error('无效的系统ID');
    }

    return system;
  }

  /**
   * 根据类型查找系统
   * @param type 系统类型
   * @returns 系统列表
   */
  async findByType(type: SystemType): Promise<ISystemDocument[]> {
    if (!Object.values(SystemType).includes(type)) {
      throw new Error('无效的系统类型');
    }
    return await this.model.find({ systemType: type }).exec();
  }

  /**
   * 根据状态查找系统
   * @param status 系统状态
   * @returns 系统列表
   */
  async findByStatus(status: SystemStatus): Promise<ISystemDocument[]> {
    if (!Object.values(SystemStatus).includes(status)) {
      throw new Error('无效的系统状态');
    }
    return await this.model.find({ status }).exec();
  }

  /**
   * 查找所有系统（支持分页和筛选）
   * @param options 查询选项
   * @returns 分页结果
   */
  async findAllPaginated(options: {
    page?: number;
    limit?: number;
    type?: SystemType;
    status?: SystemStatus;
    maintainer?: mongoose.Types.ObjectId;
    populate?: string[];
  } = {}): Promise<{
    systems: ISystemDocument[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    const { page = 1, limit = 10, type, status, maintainer, populate = [] } = options;

    // 验证参数
    if (page < 1 || limit < 1) {
      throw new Error('页码和每页数量必须大于0');
    }

    if (type && !Object.values(SystemType).includes(type)) {
      throw new Error('无效的系统类型');
    }

    if (status && !Object.values(SystemStatus).includes(status)) {
      throw new Error('无效的系统状态');
    }

    if (maintainer && !mongoose.Types.ObjectId.isValid(maintainer)) {
      throw new Error('无效的维护者ID');
    }

    // 构建查询条件
    const query: any = {};
    if (type) query.type = type;
    if (status) query.status = status;
    if (maintainer) query.maintainer = maintainer;

    // 执行查询
    const skip = (page - 1) * limit;
    let queryBuilder = this.model.find(query).skip(skip).limit(limit).sort({ createdAt: -1 });

    // 添加populate
    populate.forEach(field => {
      queryBuilder = queryBuilder.populate(field);
    });

    const [systems, total] = await Promise.all([
      queryBuilder.exec(),
      this.model.countDocuments(query)
    ]);

    return {
      systems,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit)
    };
  }

  /**
   * 搜索系统
   * @param keyword 关键词
   * @param options 搜索选项
   * @returns 搜索结果
   */
  async search(keyword: string, options: {
    page?: number;
    limit?: number;
    type?: SystemType;
    status?: SystemStatus;
  } = {}): Promise<{
    systems: ISystemDocument[];
    total: number;
    page: number;
    limit: number;
    totalPages: number;
  }> {
    if (!keyword || typeof keyword !== 'string') {
      throw new Error('搜索关键词不能为空');
    }

    const { page = 1, limit = 10, type, status } = options;

    // 验证参数
    if (page < 1 || limit < 1) {
      throw new Error('页码和每页数量必须大于0');
    }

    if (type && !Object.values(SystemType).includes(type)) {
      throw new Error('无效的系统类型');
    }

    if (status && !Object.values(SystemStatus).includes(status)) {
      throw new Error('无效的系统状态');
    }

    // 构建搜索条件
    const query: any = {
      $or: [
        { systemName: { $regex: keyword, $options: 'i' } },
        { systemCode: { $regex: keyword, $options: 'i' } },
        { description: { $regex: keyword, $options: 'i' } }
      ]
    };

    if (type) query.systemType = type;
    if (status) query.status = status;

    const skip = (page - 1) * limit;

    const [systems, total] = await Promise.all([
      this.model.find(query).skip(skip).limit(limit).sort({ createdAt: -1 }).exec(),
      this.model.countDocuments(query)
    ]);

    return {
      systems,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit)
    };
  }

  /**
   * 获取系统统计信息
   * @returns 统计信息
   */
  async getStatistics(): Promise<{
    total: number;
    byStatus: Record<SystemStatus, number>;
    byType: Record<SystemType, number>;
    activeCount: number;
  }> {
    const [total, statusStatsRaw, activeCount] = await Promise.all([
      this.model.countDocuments(),
      this.model.aggregate([
        {
          $group: {
            _id: '$status',
            count: { $sum: 1 }
          }
        }
      ]),
      this.model.countDocuments({ status: SystemStatus.ACTIVE })
    ]);

    // 转换状态统计格式，确保所有状态都有默认值
    const statusStats: Record<SystemStatus, number> = {
      [SystemStatus.ACTIVE]: 0,
      [SystemStatus.INACTIVE]: 0,
      [SystemStatus.SUSPENDED]: 0,
      [SystemStatus.MAINTENANCE]: 0
    };
    
    statusStatsRaw.forEach((item: any) => {
      statusStats[item._id as SystemStatus] = item.count;
    });

    // 获取类型统计
    const typeStats = await this.model.aggregate([
      {
        $group: {
          _id: '$type',
          count: { $sum: 1 }
        }
      }
    ]);

    const byType = typeStats.reduce((acc: Record<SystemType, number>, item: any) => {
      acc[item._id as SystemType] = item.count;
      return acc;
    }, {} as Record<SystemType, number>);

    return {
      total,
      byStatus: statusStats,
      byType,
      activeCount
    };
  }

  /**
   * 验证系统访问权限
   * @param systemId 系统ID
   * @param user 用户信息
   * @returns 是否有访问权限
   */
  async verifyAccess(systemId: mongoose.Types.ObjectId | string, user: IUser): Promise<boolean> {
    if (!mongoose.Types.ObjectId.isValid(systemId)) {
      throw new Error('无效的系统ID');
    }

    if (!user || !user._id) {
      throw new Error('无效的用户信息');
    }

    const system = await this.model.findById(systemId);
    if (!system) {
      return false;
    }
    // 检查系统状态是否为活跃
    return system.status === SystemStatus.ACTIVE;
  }

  /**
   * 重新生成系统密钥
   * @param id 系统ID
   * @param updatedBy 更新者ID
   * @returns 更新后的系统文档
   */
  async regenerateSecret(id: mongoose.Types.ObjectId | string, updatedBy?: mongoose.Types.ObjectId): Promise<ISystemDocument> {
    if (!mongoose.Types.ObjectId.isValid(id)) {
      throw new Error('无效的系统ID');
    }

    const system = await this.model.findById(id);
    if (!system) {
      throw new Error('无效的系统ID');
    }

    // 生成新的密钥
    const newSecret = require('crypto').randomBytes(32).toString('hex');
    system.secretKey = newSecret;
    system.lastActiveAt = new Date();
    if (updatedBy) {
      system.updatedBy = updatedBy;
    }

    return await system.save();
  }

  /**
   * 批量创建系统
   * @param systemsData 系统数据数组
   * @returns 创建结果
   */
  async batchCreate(systemsData: Array<{
    systemName: string;
    systemCode: string;
    description?: string;
    systemType: SystemType;
    version?: string;
    createdBy?: mongoose.Types.ObjectId;
    callbackUrl?: string;
    allowedOrigins?: string[];
    metadata?: Record<string, any>;
    status?: SystemStatus;
  }>): Promise<{
    success: ISystemDocument[];
    failed: Array<{ data: any; error: string }>;
  }> {
    if (!Array.isArray(systemsData) || systemsData.length === 0) {
      throw new Error('系统数据不能为空');
    }

    const success: ISystemDocument[] = [];
    const failed: Array<{ data: any; error: string }> = [];

    for (const systemData of systemsData) {
      try {
        const system = await this.create(systemData);
        success.push(system);
      } catch (error) {
        failed.push({
          data: systemData,
          error: error instanceof Error ? error.message : '未知错误'
        });
      }
    }

    return { success, failed };
  }

  /**
   * 获取活跃系统数量
   * @returns 活跃系统数量
   */
  async getActiveCount(): Promise<number> {
    return await this.model.countDocuments({ status: SystemStatus.ACTIVE });
  }

  /**
   * 清理非活跃系统
   * @param inactiveDays 非活跃天数阈值
   * @returns 清理结果
   */
  async cleanupInactive(inactiveDays: number = 90): Promise<{
    deletedCount: number;
    deletedSystems: string[];
  }> {
    if (inactiveDays < 1) {
      throw new Error('非活跃天数必须大于0');
    }

    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - inactiveDays);

    const inactiveSystems = await this.model.find({
      status: SystemStatus.INACTIVE,
      lastActiveAt: { $lt: cutoffDate }
    });

    const deletedSystems = inactiveSystems.map((s: ISystemDocument) => s.systemCode);
    const result = await this.model.deleteMany({
      status: SystemStatus.INACTIVE,
      lastActiveAt: { $lt: cutoffDate }
    });

    return {
      deletedCount: result.deletedCount || 0,
      deletedSystems
    };
  }

  /**
   * 软删除系统
   * @param id 系统ID
   * @returns 删除结果
   */
  async delete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    if (!mongoose.Types.ObjectId.isValid(id)) {
      throw new Error('无效的系统ID');
    }

    const result = await this.model.findByIdAndUpdate(
      id,
      {
        status: SystemStatus.INACTIVE,
        deletedAt: new Date(),
        updatedAt: new Date()
      },
      { new: true }
    );

    return !!result;
  }

  /**
   * 硬删除系统
   * @param id 系统ID
   * @returns 删除结果
   */
  async hardDelete(id: mongoose.Types.ObjectId | string): Promise<boolean> {
    if (!mongoose.Types.ObjectId.isValid(id)) {
      throw new Error('无效的系统ID');
    }

    const result = await this.model.findByIdAndDelete(id);
    return !!result;
  }
}

export default SystemDAO;
